/*
 * 文件名：WsFlowProcessImpl.java
 * 版权：Copyright by http://www.infopub.top/
 * 描述：
 * 修改人：Awoke
 * 修改时间：2019年12月13日
 * 跟踪单号：
 * 修改单号：
 * 修改内容：
 */

package top.infopub.mgr.flow.service.impl;


import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import top.infopub.mgr.cap.service.CapProcessManageService;
import top.infopub.mgr.exception.FlowProcessException;
import top.infopub.mgr.flow.cnst.FlowTemplateEnum;
import top.infopub.mgr.flow.domain.ProcessNodeDomain;
import top.infopub.mgr.flow.service.*;
import top.infopub.mgr.flow.vo.ProcessNodeVo;
import top.infopub.mgr.hr.domain.StaffOfficeDomain;
import top.infopub.mgr.hr.service.*;
import top.infopub.mgr.mkt.dao.*;
import top.infopub.mgr.mkt.service.PreProjectService;
import top.infopub.mgr.mkt.service.ProPlotService;
import top.infopub.mgr.mkt.service.ProProcessManageService;
import top.infopub.mgr.mkt.service.SetupProService;
import top.infopub.mgr.mkt.vo.PreProjectCoopVo;
import top.infopub.mgr.mkt.vo.PreProjectVo;
import top.infopub.mgr.mkt.vo.SetupProCoopVo;
import top.infopub.mgr.mkt.vo.SetupProVo;
import top.infopub.mgr.sys.service.OperatorService;
import top.infopub.mgr.util.DateUtils;
import top.infopub.model.flow.Process;
import top.infopub.model.flow.*;
import top.infopub.model.hr.DeptInfo;
import top.infopub.model.hr.OrgInfo;
import top.infopub.model.hr.PostGroup;
import top.infopub.model.hr.StaffInfo;
import top.infopub.model.mkt.*;
import top.infopub.model.sys.Operator;
import top.infopub.security.util.SessionUserUtils;
import top.infopub.security.vo.AuthorizationVO;
import top.infopub.tdp.sys.service.CodeGeneratorConfigService;
import top.infopub.tdp.util.BizParaUtil;
import top.infopub.util.IdFactory;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;


/**
 * 工作审批流程相关服务方法 实现
 * @author Awoke
 * @version 2019年12月13日
 * @see WsFlowProcessServiceImpl
 * @since
 */
@Service
public class WsFlowProcessServiceImpl implements WsFlowProcessService {

    @Autowired
    private TemplateService templateService;

    @Autowired
    private TemplateNodeService templateNodeService;

    @Autowired
    private ProcessService processService;

    @Autowired
    private ProcessNodeService processNodeService;

    @Autowired
    private ProcessNodeAttService processNodeAttService;

    @Autowired
    private StaffOfficeService staffOfficeService;

    @Autowired
    private StaffInfoService staffInfoService;

    @Autowired
    private OrgInfoService orgInfoService;

    @Autowired
    private WsStaffOfficeService wsStaffOfficeService;

    @Autowired
    private OperatorService operatorService;

    @Autowired
    private OAFlowService oaFlowService;

    @Autowired
    private PostGroupService postGroupService;

    @Autowired
    private PostInfoService postInfoService;

    @Autowired @Lazy
    private PreProjectService preProjectService;

    @Autowired
    private ProPlotDao proPlotDao;

    @Autowired @Lazy
    private ProPlotService proPlotService;

    @Autowired @Lazy
    private SetupProService setupProService;

    @Autowired
    private SetupProDao setupProDao;
    @Autowired
    private SetupProAttDao setupProAttDao;
    @Autowired
    private SetupProCoopDao setupProCoopDao;
    @Autowired
    private SetupProSubDao setupProSubDao;

    @Autowired
    private ProSellDao proSellDao;
    @Autowired
    private ProSellCoopDao proSellCoopDao;
    @Autowired
    private ProSellSubDao proSellSubDao;

    @Autowired
    private InquiryProDao inquiryProDao;
    @Autowired
    private InquiryProCoopDao inquiryProCoopDao;
    @Autowired
    private InquiryProSubDao inquiryProSubDao;

    @Autowired
    private DeptInfoService deptInfoService;

    @Autowired
    private CodeGeneratorConfigService codeGeneratorConfigService;

    @Lazy
    @Autowired
    private ProProcessManageService proProcessManageService;

    @Lazy
    @Autowired
    private CapProcessManageService capProcessManageService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void launch(String templateId, String srcBizTable, String srcBizSguid, String processId, String oaTitle) {
        // 判断是否有效
        if (StringUtils.isBlank(templateId)) {
            throw new FlowProcessException("无效的工作流模板ID~");
        }
        AuthorizationVO vo = SessionUserUtils.getSessionAttributeForUserDtl();
        // 发起人ID
        String startUserId = vo.getId();
        // 发起人姓名
        String startRealName = vo.getRealName();
        // 发起人时间
        Date startDate = new Date();

        Template queryTemplate = new Template();
        queryTemplate.setId(templateId);
        queryTemplate.setIsUsable("1");// 可用
        List<Template> templates = templateService.selectByEntityWhere(queryTemplate);
        if (templates == null || templates.size() < 1) {
            throw new FlowProcessException("获取不到对应的工作流模板数据~");
        }
        // 工作流模板名称
        String templateName = templates.get(0).getSname();

        // 模板节点数据 按照节点索引正序
        List<TemplateNode> templateNodeList = Lists.newLinkedList();
        TemplateNode queryModel = new TemplateNode();
        queryModel.setTemplateId(templateId);
        queryModel.setSrcBizTable(srcBizTable);
        //queryModel.setNodePolicy(1);// 审批流程
        templateNodeList = templateNodeService.selectByEntityWhere(queryModel);
        if (templateNodeList.size() < 2) {
            throw new FlowProcessException("获取不到对应的工作流节点数据，首个节点需要包含一个审批/会签节点~");
        }
        TemplateNode templateNode_1 = templateNodeList.get(0);
        List<TemplateNode> templateNode_2s=new ArrayList<>();
        if(templateNodeList.get(1).getNodePolicy()==1){
            templateNode_2s.add(templateNodeList.get(1));
        }
        /**
         * 修改人：张能
         * 修改逻辑为第一个审批为知会也可以走，因为市场模块的投标保证金都是知会
         */
//        if(templateNodeList.get(1).getNodePolicy()==2){
//            throw new FlowProcessException("获取不到对应的工作流节点数据，首个节点需要包含一个审批/会签节点~");
//        }
        if(templateNodeList.get(1).getNodePolicy()==3){
            for (int i = 0; i <templateNodeList.size() ; i++) {
                if(i>0&&templateNodeList.get(i).getNodePolicy()==3&&templateNodeList.get(i).getNodeIdx()==templateNodeList.get(1).getNodeIdx()){
                    templateNode_2s.add(templateNodeList.get(i));
                }
            }
        }
        //TemplateNode templateNode_2 = templateNodeList.get(1);

        // 新增审批流程
        Process process = new Process();
        process.setId(processId);// 设置id
        process.setTemplateId(templateId);
        process.setTemplateName(templateName);
        process.setStartUserId(startUserId);
        process.setStartRealName(startRealName);
        process.setStartTime(startDate);
        process.setNowIdx(2); // 当前索引为2
        process.setMaxIdx(templateNodeList.get(templateNodeList.size() - 1).getNodeIdx());// 最大索引
        process.setProcessStatus("1"); // 当前审批状态 1=审批中 9=审批完成 10=审批终止
        process.setSrcBizTable(srcBizTable);
        process.setSrcBizSguid(srcBizSguid);
        process.setStartOrgId(String.valueOf(SessionUserUtils.getSessionAttribute("bindOrgId")));
        process.setStartOrgName(String.valueOf(SessionUserUtils.getSessionAttribute("bindOrgName")));
        process.setStartDeptId(String.valueOf(SessionUserUtils.getSessionAttribute("bindDeptId")));
        process.setStartDeptName(String.valueOf(SessionUserUtils.getSessionAttribute("bindDeptName")));
        processService.insert(process);

        // 新增审批发起节点
        ProcessNode node_1 = new ProcessNode();
        node_1.setAddTime(startDate);
        node_1.setProcessId(processId);
        node_1.setNodeIdx(templateNode_1.getNodeIdx());
        node_1.setNodeName(templateNode_1.getNodeName());
        node_1.setDealUserId(startUserId);
        node_1.setDealName(startRealName);
        node_1.setDealTime(startDate);
        node_1.setState("1");
        node_1.setDealIdea("发起审批");
        node_1.setSrcBizTable(srcBizTable);
        node_1.setSrcBizSguid(srcBizSguid);
        node_1.setUserOrgId(String.valueOf(SessionUserUtils.getSessionAttribute("bindOrgId")));
        node_1.setUserOrgName(String.valueOf(SessionUserUtils.getSessionAttribute("bindOrgName")));
        node_1.setUserDeptId(String.valueOf(SessionUserUtils.getSessionAttribute("bindDeptId")));
        node_1.setUserDeptName(String.valueOf(SessionUserUtils.getSessionAttribute("bindDeptName")));
        node_1.setNodePolicy(1);// 审批
        processNodeService.insert(node_1);

        if(templateNodeList.get(1).getNodePolicy()==2){
            //知会流程
            if (srcBizTable.startsWith("MKT_")) {
                int idx = proProcessManageService.notifyProcess(templateId, 1, processId, srcBizTable, srcBizSguid);
                //返回0，表示从第二个节点开始都是知会流程
                if (idx == 0) return;
                //返回非0，取下一个节点
                TemplateNode newTempNode = templateNodeService.queryNextIdxsNodes(templateId, idx + 1);
                templateNode_2s = new ArrayList<>();
                templateNode_2s.add(newTempNode);
            } else if (srcBizTable.startsWith("CAP_")) {
                int idx = capProcessManageService.notifyProcess(templateId, 1, processId, srcBizTable, srcBizSguid);
                //返回0，表示从第二个节点开始都是知会流程
                if (idx == 0) return;
                //返回非0，取下一个节点
                TemplateNode newTempNode = templateNodeService.queryNextIdxsNodes(templateId, idx + 1);
                templateNode_2s = new ArrayList<>();
                templateNode_2s.add(newTempNode);
            }
        }
        for (TemplateNode templateNode_2 : templateNode_2s) {
            Integer nodePolicy = templateNode_2.getNodePolicy();// 1=审批 2=知会 3=会签
            //String tempCheckUserId = checkUserIds(templateNode_2.getId());
            List<String> checkUserIds = checkUserIds(templateNode_2.getId(),processId);
            for (String tempCheckUserId : checkUserIds) {
                //发起OA待办
                if (StringUtils.isBlank(oaTitle)) oaTitle = process.getTemplateName();
                String oaId = oaFlowService.sendOAToDo(oaTitle, SessionUserUtils.getSessionUserId(), tempCheckUserId, srcBizTable, srcBizSguid);
//                if(StringUtils.isEmpty(oaId)){
//                    throw new FlowProcessException("发起OA待办失败，请联系管理员");
//                }

                // 新增审批发起节点后的次节点
                ProcessNode node_2 = new ProcessNode();
                node_2.setAddTime(new Date());
                node_2.setProcessId(processId);
                node_2.setNodeIdx(templateNode_2.getNodeIdx());
                node_2.setNodeName(templateNode_2.getNodeName());
                node_2.setNodePolicy(templateNode_2.getNodePolicy());// 权限
                node_2.setDealUserId(tempCheckUserId);// 处理人取模板中的审核人
                node_2.setDealName(dealNameOf(tempCheckUserId).getSrealName());// 增加处理人姓名
                node_2.setState("-1");// 次节点的审批状态为初始-待审批
                node_2.setSrcBizTable(srcBizTable);
                node_2.setSrcBizSguid(srcBizSguid);
                node_2.setOaId(oaId);
                processNodeService.insert(node_2);
            }

        }




    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void launch(FlowTemplateEnum templateEnum, String srcBizSguid, String processId, String oaTitle) {
        // 模板ID
        String templateId = templateEnum.getTemplateId();
        // 获得关联业务表名
        String srcBizTable = templateEnum.getSrcBizTable();
        // 调用方法
        launch(templateId, srcBizTable, srcBizSguid, processId, oaTitle);
    }

    @Override
    @Transactional
    public void dealWith(String srcBizSguid, String processId, String state, String dealIdea,
                         String[] fileAtt) {
        Process proc = processService.selectByPrimaryKey(processId);
        if (proc == null) {
            throw new FlowProcessException("获取不到对应的审批主数据~~");
        }
        // 当前索引
        Integer nowIdx = proc.getNowIdx();
        // 模板ID
        String templateId = proc.getTemplateId();
        // 获得关联业务表名
        String srcBizTable = proc.getSrcBizTable();
        AuthorizationVO vo = SessionUserUtils.getSessionAttributeForUserDtl();
        // 操作人ID
        String userId = vo.getId();
        // 操作人姓名
        String realName = vo.getRealName();
        // 直接修改原业务表数据的sql
        StringBuilder sql = new StringBuilder();
        sql.append("update ").append(srcBizTable).append(" set process_status=? where sguid='").append(
            srcBizSguid).append("'");

        Template queryTemplate = new Template();
        queryTemplate.setId(templateId);
        queryTemplate.setIsUsable("1");// 可用
        List<Template> templates = templateService.selectByEntityWhere(queryTemplate);
        if (templates == null || templates.size() < 1) {
            throw new FlowProcessException("获取不到对应的工作流模板数据~");
        }
        // 查询当前模板剩余的【审批】节点信息 nodex>nowIdx 按照节点索引正序 (不查询[知会]节点)
        List<TemplateNode> templateNodeList = templateNodeService.queryRestNodes(templateId,nowIdx);
        if (templateNodeList == null) {
            throw new FlowProcessException("获取不到对应的工作流节点数据~");
        }

        // 【重要】特殊处理，融资-立项的 副总有最终审批权， [轮到副总审批时]，移除最后的董事长node，使副总作为最后节点
        TemplateNode capSetupFinLast = new TemplateNode();
        if (srcBizTable.equalsIgnoreCase("CAP_SETUP_FIN")) {
            String triggerNodeIdx = BizParaUtil.get("flow_cap_setup_fin_trigger");
            Integer triggerNodeIdxInt = Integer.valueOf(triggerNodeIdx);
            if (nowIdx.equals(triggerNodeIdxInt)) {
                capSetupFinLast = templateNodeList.get(templateNodeList.size() - 1);
                templateNodeList.remove(templateNodeList.size() - 1);
            }
        }

        ProcessNode nowProcNode = new ProcessNode();
        // 非最后一步审核
        if (templateNodeList.size() > 0) {
            // 查询当前审批流程节点
            ProcessNode procNodeWhere = new ProcessNode();
            procNodeWhere.setProcessId(processId);
            procNodeWhere.setNodeIdx(nowIdx);
            procNodeWhere.setState("-1"); // 未审批
            procNodeWhere.setDealUserId(userId);// 审批人为当前操作人
            List<ProcessNode> queryProcessNodes = processNodeService.selectByEntityWhere(procNodeWhere);
            if (queryProcessNodes == null || queryProcessNodes.size() < 1) {
                throw new FlowProcessException("获取不到有效的审批节点数据~");
            }
            // 处理当前审批节点数据
            nowProcNode = queryProcessNodes.get(0);

            //OA待办处理
            /*if(StringUtils.isNotEmpty(nowProcNode.getOaId())){
                String oaId = nowProcNode.getOaId();
                boolean finishOA = oaFlowService.finishOA(oaId);
                if(finishOA){
                    nowProcNode.setOaFinish(0);
                }else{
                    throw new FlowProcessException("处理OA待办失败，请联系管理员");
                }
            }*/

            nowProcNode.setDealName(realName);
            nowProcNode.setDealTime(new Date());
            nowProcNode.setState(state);
            nowProcNode.setDealIdea(dealIdea);
            nowProcNode.setUserOrgId(String.valueOf(SessionUserUtils.getSessionAttribute("bindOrgId")));
            nowProcNode.setUserOrgName(String.valueOf(SessionUserUtils.getSessionAttribute("bindOrgName")));
            nowProcNode.setUserDeptId(String.valueOf(SessionUserUtils.getSessionAttribute("bindDeptId")));
            nowProcNode.setUserDeptName(String.valueOf(SessionUserUtils.getSessionAttribute("bindDeptName")));
            processNodeService.updateByPrimaryKey(nowProcNode);

            //如果是会签，则查询会签是否全部通过
            boolean huiQianFlag=true;
            if(nowProcNode.getNodePolicy()==3){
                ProcessNode hqNode=new ProcessNode();
                hqNode.setProcessId(processId);
                hqNode.setNodeIdx(nowIdx);
                List<ProcessNode> huiQianProcessNodes = processNodeService.selectByEntityWhere(hqNode);
                for (ProcessNode huiQianProcessNode : huiQianProcessNodes) {
                    if(!"1".equals(huiQianProcessNode.getState())){
                        huiQianFlag=false;
                        break;
                    }
                }
            }

            // 如果是审批通过，则生成下一步的审批节点 同时更新审批流程信息
            // 且会签全部通过
            if ("1".equals(state)) {
                if(huiQianFlag){
                    // 下一步的模板节点
                    TemplateNode nextNode = templateNodeList.get(0);
                    List<TemplateNode> nextTemplateNode=new ArrayList<>();
                    for (TemplateNode node : templateNodeList) {
                        if(nextNode.getNodeIdx()==node.getNodeIdx()){
                            nextTemplateNode.add(node);
                        }
                    }
                    for (TemplateNode templateNode : nextTemplateNode) {
                        List<String> checkUserIds = checkUserIds(templateNode.getId(),processId);
                        //String tempCheckUserId = checkUserIds(templateNode.getId());
                        for (String tempCheckUserId : checkUserIds) {
                            //发起OA待办
                            //String oaId = oaFlowService.sendOAToDo(templates.get(0).getSname(), SessionUserUtils.getSessionUserId(), tempCheckUserId);

                            ProcessNode node_next = new ProcessNode();
                            node_next.setAddTime(new Date());
                            node_next.setProcessId(processId);
                            node_next.setNodeIdx(templateNode.getNodeIdx());
                            node_next.setNodeName(templateNode.getNodeName());
                            node_next.setNodePolicy(templateNode.getNodePolicy());// 权限 审批
                            node_next.setDealUserId(tempCheckUserId);// 处理人取模板中的审核人
                            node_next.setDealName(dealNameOf(tempCheckUserId).getSrealName());// 增加处理人姓名
                            node_next.setState("-1");// 节点的审批状态为初始-待审批
                            node_next.setSrcBizTable(srcBizTable);
                            node_next.setSrcBizSguid(srcBizSguid);
                            //node_next.setOaId(oaId);
                            processNodeService.insert(node_next);
                            // 更新审批流程信息
                            proc.setNowIdx(templateNode.getNodeIdx());
                            proc.setMaxIdx(templateNodeList.get(templateNodeList.size() - 1).getNodeIdx());// 再次更新最大索引
                            processService.updateByPrimaryKey(proc);

                            // 【重要】特殊处理，市场-资格预审的 中间段的知会信息  开始
                            if (srcBizTable.equalsIgnoreCase("MKT_INQUIRY_PRO")) {
                                String triggerNodeIdx = BizParaUtil.get("flow_mkt_inquiry_pro_trigger");
                                String maxIdx = BizParaUtil.get("flow_mkt_inquiry_pro_idx_max");
                                if (StringUtils.isNotBlank(triggerNodeIdx) && StringUtils.isNotBlank(maxIdx)) {
                                    // 如果当前节点 是触发节点，则添加[中间]段的 知会节点
                                    if (StringUtils.equals(nowProcNode.getNodeIdx().toString(), triggerNodeIdx)) {
                                        Integer maxIdxInt = Integer.valueOf(maxIdx);
                                        List<TemplateNode> toNotifyList = templateNodeService.queryIdxsNotifyNodes(
                                                templateId, maxIdxInt + 1);// +1
                                        for (TemplateNode var : toNotifyList) {
                                            ProcessNode notify_next = new ProcessNode();
                                            notify_next.setAddTime(new Date());
                                            notify_next.setProcessId(processId);
                                            notify_next.setNodeIdx(var.getNodeIdx());
                                            notify_next.setNodeName(var.getNodeName());
                                            notify_next.setNodePolicy(2);// 权限 知会
                                            notify_next.setDealUserId(checkUserId(var.getId()));// 处理人取模板中的审核人
                                            notify_next.setState("1");// 节点的审批状态为-我已同意
                                            notify_next.setSrcBizTable(srcBizTable);
                                            notify_next.setSrcBizSguid(srcBizSguid);
                                            processNodeService.insert(notify_next);
                                        }
                                    }
                                }
                            }// 市场-资格预审的 中间段的知会信息  结束

                        }

                    }

                }
            }
            // 审批不通过 更新审批流程信息  更新原业务表审批状态
            else {
                proc.setEndTime(new Date());
                proc.setProcessStatus("10"); // 10=审批终止
                proc.setIsFeedback("0");
                processService.updateByPrimaryKey(proc);
                // 原业务表审批状态 修改为审批状态
                String tempSql = sql.toString().replace("?", "10");
                processService.updateBizTableProcStatus(tempSql);
            }
        }
        // 当前审核是最后一步
        else {
            // 查询当前审批流程节点
            ProcessNode procNodeWhere = new ProcessNode();
            procNodeWhere.setProcessId(processId);
            procNodeWhere.setNodeIdx(nowIdx);
            procNodeWhere.setState("-1"); // 未审批
            procNodeWhere.setDealUserId(userId);// 审批人为当前操作人
            List<ProcessNode> queryProcessNodes = processNodeService.selectByEntityWhere(procNodeWhere);
            if (queryProcessNodes == null || queryProcessNodes.size() < 1) {
                throw new FlowProcessException("获取不到对应的审批节点数据~");
            }
            // 处理当前审批节点数据
            nowProcNode = queryProcessNodes.get(0);

            //OA待办处理
            /*if(StringUtils.isNotEmpty(nowProcNode.getOaId())){
                String oaId = nowProcNode.getOaId();
                boolean finishOA = oaFlowService.finishOA(oaId);
                if(finishOA){
                    nowProcNode.setOaFinish(0);
                }else{
                    throw new FlowProcessException("处理OA待办失败，请联系管理员");
                }
            }*/

            nowProcNode.setDealName(realName);
            nowProcNode.setDealTime(new Date());
            nowProcNode.setState(state);
            nowProcNode.setDealIdea(dealIdea);
            nowProcNode.setUserOrgId(String.valueOf(SessionUserUtils.getSessionAttribute("bindOrgId")));
            nowProcNode.setUserOrgName(String.valueOf(SessionUserUtils.getSessionAttribute("bindOrgName")));
            nowProcNode.setUserDeptId(String.valueOf(SessionUserUtils.getSessionAttribute("bindDeptId")));
            nowProcNode.setUserDeptName(String.valueOf(SessionUserUtils.getSessionAttribute("bindDeptName")));
            processNodeService.updateByPrimaryKey(nowProcNode);

            //如果是会签，则查询会签是否全部通过
            boolean huiQianFlag=true;
            if(nowProcNode.getNodePolicy()==3){
                ProcessNode hqNode=new ProcessNode();
                hqNode.setProcessId(processId);
                hqNode.setNodeIdx(nowIdx);
                List<ProcessNode> huiQianProcessNodes = processNodeService.selectByEntityWhere(procNodeWhere);
                for (ProcessNode huiQianProcessNode : huiQianProcessNodes) {
                    if(!"1".equals(huiQianProcessNode.getState())){
                        huiQianFlag=false;
                        break;
                    }
                }
            }

            // 如果是审批通过，更新审批流程信息 更新原业务表审批状态
            if ("1".equals(state)) {
                if(huiQianFlag){
                    // 更新审批流程信息
                    proc.setEndTime(new Date());
                    proc.setProcessStatus("9"); // 9=审批完成
                    proc.setIsFeedback("0");
                    processService.updateByPrimaryKey(proc);
                    // 原业务表审批状态 修改审批状态
                    String tempSql = sql.toString().replace("?", "9");
                    processService.updateBizTableProcStatus(tempSql);

                    // 所有【审核】节点都通过时， 最后统一生成 后续的【知会】节点
                    List<TemplateNode> toNotifyList = templateNodeService.queryRestNotifyNodes(
                            templateId, nowIdx);
                    for (TemplateNode var : toNotifyList) {
                        List<String> strings = checkUserIds(var.getId(),processId);
                        for (String string : strings) {
                            ProcessNode node_next = new ProcessNode();
                            node_next.setDealUserId(string);// 处理人取模板中的审核人
                            node_next.setAddTime(new Date());
                            node_next.setProcessId(processId);
                            node_next.setNodeIdx(var.getNodeIdx());
                            node_next.setNodeName(var.getNodeName());
                            node_next.setNodePolicy(2);// 权限 知会
                            node_next.setState("1");// 节点的审批状态为-我已同意
                            node_next.setSrcBizTable(srcBizTable);
                            node_next.setSrcBizSguid(srcBizSguid);
                            processNodeService.insert(node_next);
                        }
                    }

                    //市场管理流程，自动复制数据到下一步的表
                    mktFlowAuto(srcBizSguid, vo, templates);

                }

            }
            // 审批不通过 更新审批流程信息 更新原业务表审批状态
            else {
                proc.setEndTime(new Date());
                proc.setProcessStatus("10"); // 10=审批终止
                proc.setIsFeedback("0");
                processService.updateByPrimaryKey(proc);
                // 原业务表审批状态 修改审批状态
                String tempSql = sql.toString().replace("?", "10");
                processService.updateBizTableProcStatus(tempSql);

                // 【重要】特殊处理，融资-立项的 副总审批拒绝，但是董事长可以继续审批  开始
                if (srcBizTable.equalsIgnoreCase("CAP_SETUP_FIN")) {
                    String triggerNodeIdx = BizParaUtil.get("flow_cap_setup_fin_trigger");
                    if (StringUtils.isNotBlank(triggerNodeIdx)) {
                        if (StringUtils.equals(nowProcNode.getNodeIdx().toString(), triggerNodeIdx)) {
                            // 董事长模板节点
                            ProcessNode node_next = new ProcessNode();
                            node_next.setAddTime(new Date());
                            node_next.setProcessId(processId);
                            node_next.setNodeIdx(capSetupFinLast.getNodeIdx());
                            node_next.setNodeName(capSetupFinLast.getNodeName());
                            node_next.setNodePolicy(capSetupFinLast.getNodePolicy());// 董事长-权限
                            String tempCheckUserId = checkUserId(capSetupFinLast.getId());
                            node_next.setDealUserId(tempCheckUserId);// 处理人取模板中的审核人
                            node_next.setDealName(dealNameOf(tempCheckUserId).getSrealName());// 增加处理人姓名
                            node_next.setState("-1");// 节点的审批状态为初始-待审批
                            node_next.setSrcBizTable(srcBizTable);
                            node_next.setSrcBizSguid(srcBizSguid);
                            processNodeService.insert(node_next);
                            // 更新审批流程信息
                            proc.setNowIdx(capSetupFinLast.getNodeIdx());
                            processService.updateByPrimaryKey(proc);
                        }
                    }
                }// 融资-立项的 副总审批拒绝，但是董事长可以继续审批  结束
            }
        }

        // 处理节点对应的附件
        List<ProcessNodeAtt> fileAtts = new ArrayList<ProcessNodeAtt>();
        // 附件
        if (fileAtt != null) {
            for (String file : fileAtt) {
                ProcessNodeAtt nodeAtt = createFileAtt(vo, processId, nowProcNode.getId(), file);
                fileAtts.add(nodeAtt);
            }
        }
        if (CollectionUtils.isNotEmpty(fileAtts)) {
            // 批量插入
            processNodeAttService.insertByBatch(fileAtts);
        }
    }

    public void mktFlowAuto(String srcBizSguid, AuthorizationVO vo, List<Template> templates) {
        String srcBizTable1 = templates.get(0).getSrcBizTable();
        //MKT_PRE_PROJECT
        switch (srcBizTable1){
            case "MKT_PRE_PROJECT":// 本次审批预立项-->立项策划
                ProPlot proPlot=new ProPlot();
                PreProjectVo preProject = preProjectService.selectById(srcBizSguid);
                proPlot.setProName(preProject.getProName());
                proPlot.setProCode(preProject.getProCode());
//                proPlot.setTypes(preProject.getTypes());
//                proPlot.setHrStaffApplyId(preProject.getHrStaffApplyId());
//                proPlot.setStaffName(preProject.getStaffName());
//                proPlot.setHrOrgId(preProject.getHrOrgId());
//                proPlot.setHrDeptId(preProject.getHrDeptId());

                String codes = "mkt_pro_plot";
                String generatorCode = codeGeneratorConfigService.generatorCode(codes);
                proPlot.setCodes(generatorCode);
                String id = IdFactory.getUUIDUpper();
                proPlot.setId(id);
                proPlot.setAddBy(vo.getId());
                proPlot.setAddTime(DateUtils.getCurrentDateTime());
                // 处理processId
                String processId1 = IdFactory.getUUIDUpper();
                proPlot.setProcessId(processId1);
                proPlot.setProcessStatus("0");//待提交
                proPlot.setUptBy(vo.getId());
                proPlot.setUptTime(DateUtils.getCurrentDateTime());
                proPlotDao.insertById(proPlot);

                //OA通知营销经理
                //发起OA待办
                //String oaId = oaFlowService.sendOAToDo(templates.get(0).getSname(), SessionUserUtils.getSessionUserId(), tempCheckUserId);

                break;
            case "MKT_PRO_PLOT":// 立项策划--> 立项和营销策划
                //TODO 提交立项
                SetupPro setupPro=new SetupPro();
                String MKT_SETUP_PRO = "mkt_setup_pro_codes";
                setupPro.setCodes(codeGeneratorConfigService.generatorCode(MKT_SETUP_PRO));
                String setupProId = IdFactory.getUUIDUpper();

                ProPlot plot = proPlotService.selectByPrimaryKey(srcBizSguid);
                List<PreProject> preProjects = preProjectService.selectByProCode(plot.getProCode());
                if(preProjects!=null&&preProjects.size()>0){
                    PreProject pre = preProjects.get(0);
                    PreProjectVo preProjectVo = preProjectService.selectById(pre.getId());
                    //preProjectVo
                    List<PreProjectCoopVo> projectCoopVos = preProjectVo.getProjectCoopVos();
                    List<PreProjectSub> preProjectSubs = preProjectVo.getPreProjectSubs();
                    //List<PreProjectAtt> preProjectAtts = preProjectVo.getPreProjectAtts();
                    List<SetupProCoop> setupProCoops=new ArrayList<>();
                    List<SetupProSub> setupProSubs=new ArrayList<>();
                    List<SetupProAtt> setupProAtts=new ArrayList<>();
                    for (PreProjectCoopVo projectCoopVo : projectCoopVos) {
                        SetupProCoop setupProCoop=new SetupProCoopVo();
                        BeanUtils.copyProperties(projectCoopVo,setupProCoop);
                        setupProCoop.setSetupProId(setupProId);
                        setupProCoop.setAddBy(vo.getId());
                        setupProCoop.setAddTime(DateUtils.getCurrentDateTime());
                        setupProCoops.add(setupProCoop);
                    }
                    for (PreProjectSub preProjectSub : preProjectSubs) {
                        SetupProSub setupProSub=new SetupProSub();
                        BeanUtils.copyProperties(preProjectSub,setupProSub);
                        setupProSub.setSetupProId(setupProId);
                        setupProSub.setAddBy(vo.getId());
                        setupProSub.setAddTime(DateUtils.getCurrentDateTime());
                        setupProSubs.add(setupProSub);
                    }
                    /*for (PreProjectAtt preProjectAtt : preProjectAtts) {
                        SetupProAtt setupProAtt=new SetupProAtt();
                        BeanUtils.copyProperties(preProjectAtt,setupProAtt);
                        setupProAtt.setSetupProId(setupProId);
                        setupProAtt.setAddBy(vo.getId());
                        setupProAtt.setAddTime(DateUtils.getCurrentDateTime());
                        setupProAtts.add(setupProAtt);
                    }*/
                    BeanUtils.copyProperties(pre,setupPro);
                   // setupProService.addSetupPro(setupPro, setupProCoops, setupProSubs, fileAtts);
                    setupPro.setId(setupProId);
                    setupPro.setAddBy(vo.getId());
                    setupPro.setAddTime(DateUtils.getCurrentDateTime());
                    // 处理processId
                    String setUpProcessId = IdFactory.getUUIDUpper();
                    setupPro.setProcessId(setUpProcessId);
                    setupPro.setProcessStatus("0");//待提交
                    setupPro.setUptBy(vo.getId());
                    setupPro.setUptTime(DateUtils.getCurrentDateTime());
                    //插入立项记录
                    setupProDao.insertById(setupPro);

                    //批量插入联合体单位
                    if(CollectionUtils.isNotEmpty(setupProCoops)){
                        setupProCoopDao.insertByBatch(setupProCoops);
                    }

                    //批量插入子项
                    if(CollectionUtils.isNotEmpty(setupProSubs)){
                        setupProSubDao.insertByBatch(setupProSubs);
                    }

                    //通知营销经理补充信息
                }



                //TODO 提交营销策划
                ProSell proSell=new ProSell();
                String MKT_PRO_SELL = "mkt_pro_sell_codes";
                proSell.setCodes(codeGeneratorConfigService.generatorCode(MKT_PRO_SELL));
                String proSellId = IdFactory.getUUIDUpper();

                if(preProjects!=null&&preProjects.size()>0){
                    PreProject pre = preProjects.get(0);
                    PreProjectVo preProjectVo = preProjectService.selectById(pre.getId());
                    //preProjectVo
                    List<PreProjectCoopVo> projectCoopVos = preProjectVo.getProjectCoopVos();
                    List<PreProjectSub> preProjectSubs = preProjectVo.getPreProjectSubs();
                    List<ProSellCoop> proSellCoops=new ArrayList<>();
                    List<ProSellSub> proSellSubs=new ArrayList<>();
                    for (PreProjectCoopVo projectCoopVo : projectCoopVos) {
                        ProSellCoop proSellCoop=new ProSellCoop();
                        BeanUtils.copyProperties(projectCoopVo,proSellCoop);
                        proSellCoop.setProSellId(proSellId);
                        proSellCoop.setAddBy(vo.getId());
                        proSellCoop.setAddTime(DateUtils.getCurrentDateTime());
                        proSellCoops.add(proSellCoop);
                    }
                    for (PreProjectSub preProjectSub : preProjectSubs) {
                        ProSellSub proSellSub=new ProSellSub();
                        BeanUtils.copyProperties(preProjectSub,proSellSub);
                        proSellSub.setProSellId(proSellId);
                        proSellSub.setAddBy(vo.getId());
                        proSellSub.setAddTime(DateUtils.getCurrentDateTime());
                        proSellSubs.add(proSellSub);
                    }

                    BeanUtils.copyProperties(pre,proSell);
                    proSell.setId(proSellId);
                    proSell.setAddBy(vo.getId());
                    proSell.setAddTime(DateUtils.getCurrentDateTime());
                    // 处理processId
                    String setUpProcessId = IdFactory.getUUIDUpper();
                    proSell.setProcessId(setUpProcessId);
                    proSell.setProcessStatus("0");//待提交
                    proSell.setUptBy(vo.getId());
                    proSell.setUptTime(DateUtils.getCurrentDateTime());
                    //插入立项记录
                    proSellDao.insertById(proSell);

                    //批量插入联合体单位
                    if(CollectionUtils.isNotEmpty(proSellCoops)){
                        proSellCoopDao.insertByBatch(proSellCoops);
                    }

                    //批量插入子项
                    if(CollectionUtils.isNotEmpty(proSellSubs)){
                        proSellSubDao.insertByBatch(proSellSubs);
                    }

                    //通知营销经理补充信息
                    //String oaId = oaFlowService.sendOAToDo("", SessionUserUtils.getSessionUserId(), tempCheckUserId);

                }


                break;
            case "MKT_SETUP_PRO": //立项-->资格预审
                InquiryPro inquiryPro =new InquiryPro();
                String MKT_INQUIRY_PRO = "mkt_inquiry_pro_codes";
                inquiryPro.setCodes(codeGeneratorConfigService.generatorCode(MKT_INQUIRY_PRO));
                String inquiryProId = IdFactory.getUUIDUpper();
                SetupProVo setupProVo = setupProService.selectById(srcBizSguid);

                List<SetupProCoopVo> setupProCoopVos = setupProVo.getSetupProCoopVos();
                List<SetupProSub> setupProSubs = setupProVo.getSetupProSubs();
                List<InquiryProCoop> inquiryProCoops=new ArrayList<>();
                List<InquiryProSub> inquiryProSubs=new ArrayList<>();
                for (SetupProCoopVo setupProCoopVo : setupProCoopVos) {
                    InquiryProCoop inquiryProCoop=new InquiryProCoop();
                    BeanUtils.copyProperties(setupProCoopVo,inquiryProCoop);
                    inquiryProCoop.setId(IdFactory.getUUIDUpper());
                    inquiryProCoop.setInquiryProId(inquiryProId);
                    inquiryProCoop.setAddBy(vo.getId());
                    inquiryProCoop.setAddTime(DateUtils.getCurrentDateTime());
                    inquiryProCoops.add(inquiryProCoop);
                }
                for (SetupProSub setupProSub : setupProSubs) {
                    InquiryProSub inquiryProSub=new InquiryProSub();
                    BeanUtils.copyProperties(setupProSub,inquiryProSub);
                    inquiryProSub.setId(IdFactory.getUUIDUpper());
                    inquiryProSub.setInquiryProId(inquiryProId);
                    inquiryProSub.setAddBy(vo.getId());
                    inquiryProSub.setAddTime(DateUtils.getCurrentDateTime());
                    inquiryProSubs.add(inquiryProSub);
                }

                BeanUtils.copyProperties(setupProVo,inquiryPro);
                inquiryPro.setId(inquiryProId);
                inquiryPro.setAddBy(vo.getId());
                inquiryPro.setAddTime(DateUtils.getCurrentDateTime());
                // 处理processId
                String inquiryProProcessId = IdFactory.getUUIDUpper();
                inquiryPro.setProcessId(inquiryProProcessId);
                inquiryPro.setProcessStatus("0");//待提交
                inquiryPro.setUptBy(vo.getId());
                inquiryPro.setUptTime(DateUtils.getCurrentDateTime());
                //插入资格预审记录
                inquiryProDao.insertById(inquiryPro);
                //批量插入联合体单位
                if(CollectionUtils.isNotEmpty(inquiryProCoops)){
                    inquiryProCoopDao.insertByBatch(inquiryProCoops);
                }

                //批量插入子项
                if(CollectionUtils.isNotEmpty(inquiryProSubs)){
                    inquiryProSubDao.insertByBatch(inquiryProSubs);
                }
                //通知营销经理补充信息

                break;
            case "MKT_PRO_SELL"://营销策划-->
                break;
            case "MKT_INQUIRY_PRO"://资格预审-->招标文件分析
                break;
            case "1"://招标文件分析-->标书策划
                break;
            case "2"://标书策划 --> 投标决策
                break;
            case "MKT_DECI_PRO"://投标决策-->投标保证金申请
                break;
            case "MKT_BID_BOND_APPLY"://投标保证金申请-->项目投标
                break;
            case "3"://项目投标-->交底
                break;
            case "MKT_DISCLOSE_PRO" ://交底-->标后总结
                break;
            default:
        }
    }

    @Override
    public List<ProcessNodeDomain> queryPendingProcNodes(String srcBizTable) {
        // 当前登录用户
        return processNodeService.queryPendingProcNodes(SessionUserUtils.getSessionUserId(),
            srcBizTable);
    }

    @Override
    public Page<ProcessNodeDomain> queryPagePendingProcNodes(String srcBizTable,
                                                             Page<ProcessNodeDomain> page) {
        PageHelper.startPage(page.getPageNum(), page.getPageSize());
        return (Page<ProcessNodeDomain>)processNodeService.queryPendingProcNodes(
            SessionUserUtils.getSessionUserId(), srcBizTable);
    }

    @Override
    public Map<String, Object> queryProcAndAllNodes(String processId) {
        Map<String, Object> result = Maps.newHashMap();
        List<ProcessNodeVo> all = Lists.newLinkedList();
        // 查询所有已审批
        List<ProcessNodeVo> already = processNodeService.queryAllProcNodes(processId);
        // 查询所有待审批-工作流模板节点
        List<ProcessNodeVo> rest = Lists.newLinkedList();
        Process proc = processService.selectByPrimaryKey(processId);
        String templateId = proc.getTemplateId();
        Integer nowIdx = proc.getNowIdx();
        List<TemplateNode> templateNodes = templateNodeService.queryRestNodes(templateId, nowIdx);
        for (TemplateNode var : templateNodes) {
            ProcessNodeVo node = new ProcessNodeVo();
            node.setProcessId(processId);
            node.setNodeIdx(var.getNodeIdx());
            node.setNodeName(var.getNodeName());
            node.setDealUserId(var.getCheckUserId());
            node.setNodePolicy(var.getNodePolicy());// 节点权限 1=审批 2=知会 默认1
            node.setState("-2");// 待流转
            rest.add(node);
        }
        all.addAll(already);
        all.addAll(rest);
        // 已审批 + 待审批 节点
        result.put("sharedAllNodes", all);
        // 当前节点
        result.put("sharedNowIdx", proc.getNowIdx());
        // 最大节点
        result.put("sharedMaxIdx", proc.getMaxIdx());
        return result;
    }

    @Override
    public String queryTemplateIdByTable(String srcBizTable) {
        Map<String, Object> where = Maps.newHashMap();
        where.put("srcBizTable", srcBizTable);
        where.put("isUsable", "1");
        where.put("orderCondition", " add_time desc ");
        List<Template> list = templateService.selectByMapWhere(where);
        if (null == list || list.size() == 0) {
            throw new FlowProcessException("获取不到对应的工作流模板数据~");
        }
        return list.get(0).getId();
    }

    @Override
    public String queryTemplateIdByTableBranch(String srcBizTable, String branchCode) {
        Map<String, Object> where = Maps.newHashMap();
        where.put("srcBizTable", srcBizTable);
        where.put("isUsable", "1");
        where.put("branchCode", branchCode);
        where.put("orderCondition", " add_time desc ");
        List<Template> list = templateService.selectByMapWhere(where);
        if (null == list || list.size() == 0) {
            throw new FlowProcessException("获取不到对应的工作流模板数据~");
        }
        return list.get(0).getId();
    }

    @Override
    public String queryTemplateIdByOrg(String srcBizTable, String hrOrgId) {
        Map<String, Object> where = Maps.newHashMap();
        where.put("srcBizTable", srcBizTable);
        where.put("isUsable", "1");
        where.put("hrOrgId", hrOrgId);
        where.put("orderCondition", " add_time desc ");
        List<Template> list = templateService.selectByMapWhere(where);
        if (null == list || list.size() == 0) {
            throw new FlowProcessException("获取不到对应的工作流模板数据~");
        }
        return list.get(0).getId();
    }

    @Override
    public List<String> checkUserIds(String templateNodeId,String processId ){
        Process proc = processService.selectByPrimaryKey(processId);
        if (proc == null) {
            throw new FlowProcessException("获取不到对应的审批主数据~~");
        }
        //查询发起人的部门和公司
        String startDeptId = proc.getStartDeptId();
        String startOrgId = proc.getStartOrgId();

        Object bindOrgIdObj = SessionUserUtils.getSessionAttribute("bindOrgId");
        Object bindDeptIdObj = SessionUserUtils.getSessionAttribute("bindDeptId");
        if (bindOrgIdObj == null || bindDeptIdObj == null) {
            throw new FlowProcessException("当前用户未绑定公司或部门，不能审批~");
        }
        // 审批节点
        TemplateNode templateNode = templateNodeService.selectByPrimaryKey(templateNodeId);
        if (templateNode == null) {
            throw new FlowProcessException("获取不到相应审批节点，有可能因：审批流程已调整~");
        }
        //节点选择标识 1=集团总部 2=区域公司 3=本公司 4=本部门内
        Integer routerFlag = templateNode.getRouteFlag();
        // 当前用户所在的公司
        String bindOrgId = String.valueOf(bindOrgIdObj);
        // 当前用户所在的部门
        String bindDeptId = String.valueOf(bindDeptIdObj);

        Integer nodePolicy = templateNode.getNodePolicy();

        // 审批角色组id
        String chooseKey = templateNode.getChooseKey();
        PostGroup postGroup = postGroupService.selectByPrimaryKey(chooseKey);


        List<Operator> operators=new ArrayList<>();
        if("1".equals(postGroup.getRoleType())||routerFlag==4||routerFlag==5){
            switch (routerFlag){
                case 1://集团总部
                    String super_org_id = BizParaUtil.get("super_org_id");
                    OrgInfo orgInfo=new OrgInfo();
                    orgInfo.setTypes("1");
                    List<OrgInfo> orgInfos = orgInfoService.selectByEntityWhere(orgInfo);
                    List<String> orgIds=new ArrayList<>();
                    for (OrgInfo info : orgInfos) {
                        orgIds.add(info.getId());
                    }
                    operators = operatorService.selectOperatorByGroupIdOrgIdsPost(postGroup.getId(), postGroup.getRoleType(),orgIds);
                    break;
                case 2://区域公司
                    OrgInfo my = orgInfoService.selectByPrimaryKey(bindOrgId);
                    OrgInfo myParent = orgInfoService.selectByPrimaryKey(my.getParentId());
                    // 必须当前公司是项目公司 且 父级公司是 区域公司
                    if (my.getTypes().equals("3") && myParent.getTypes().equals("2")) {
                        operators = operatorService.selectOperatorByGroupIdPost(postGroup.getId(), postGroup.getRoleType(),myParent.getId(),null);
                    }
                    else {
                        throw new FlowProcessException("审批节点获取直属上级区域公司无效。请联系：流程管理员~");
                    }
                    break;
                case 3://项目公司 本公司
                    operators = operatorService.selectOperatorByGroupIdPost(postGroup.getId(), postGroup.getRoleType(),bindOrgId,null);
                    break;
                case 4://本部门  部门负责人
                    //operators = operatorService.selectOperatorByGroupIdPost(postGroup.getId(), postGroup.getRoleType(),startOrgId,startDeptId);
                    DeptInfo deptInfo = deptInfoService.selectByPrimaryKey(startDeptId);
                    if(deptInfo==null||StringUtils.isEmpty(deptInfo.getFzrcode())){
                        throw new FlowProcessException("未查询到部门负责人。请联系：流程管理员~");
                    }
                    StaffInfo deptfzr=staffInfoService.selectByCode(deptInfo.getFzrcode());
                    Operator deptop=new Operator();
                    deptop.setHrStaffId(deptfzr.getId());
                    operators = operatorService.selectByEntityWhere(deptop);
                    break;
                case 5:
                    //公司法人
                    OrgInfo startOrg = orgInfoService.selectByPrimaryKey(startOrgId);
                    if(startOrg==null||StringUtils.isEmpty(startOrg.getFzrcode())){
                        throw new FlowProcessException("未查询到公司法人。请联系：流程管理员~");
                    }
                    StaffInfo staffInfo=staffInfoService.selectByCode(startOrg.getFzrcode());
                    Operator op=new Operator();
                    op.setHrStaffId(staffInfo.getId());
                    operators = operatorService.selectByEntityWhere(op);
                    break;
            }

        }else{
            //人员
           operators = operatorService.selectOperatorByGroupIdUser(postGroup.getId(), postGroup.getRoleType());
        }
        if(nodePolicy==1&&operators.size()>1){//依次审批
            throw new FlowProcessException("依次审批节点审批组【"+postGroup.getName()+"】存在多个人员，请联系管理员");
        }
        if(operators.size()==0){
            throw new FlowProcessException("审批节点【"+postGroup.getName()+"】未查询到人员信息，请联系管理员");
        }

        List<String> userIds=new ArrayList<>();
        for (Operator operator : operators) {
            userIds.add(operator.getId());
        }
        return userIds;

        // 根据选择标识，判断获取对应的审批人sys_operator_id
       /* switch (routerFlag) {
            case 1: // 直接返回审批人sys_operator_id
                return chooseKey;
            case 2: // 在本部门内找[部门负责人]岗位的人，获取其sys_operator_id
                StaffOfficeDomain where_2 = new StaffOfficeDomain();
                where_2.setOrgId(bindOrgId);
                where_2.setDeptId(bindDeptId);// 审批人所在的部门
                where_2.setPostName(chooseKey); // 对应的岗位，比如是 部门负责人
                List<StaffOfficeDomain> res_2 = staffOfficeService.selectStaffByPostName(where_2);
                // 判断审批人是否唯一
                asserts(res_2, chooseKey, templateNode);
                return res_2.get(0).getSysOperatorId();
            case 3:// 3=本公司(项目/区域)内，通过岗位查询对应审批人
                StaffOfficeDomain where_3 = new StaffOfficeDomain();
                where_3.setOrgId(bindOrgId);
                where_3.setPostName(chooseKey); // 对应的岗位
                List<StaffOfficeDomain> res_3 = staffOfficeService.selectStaffByPostName(where_3);
                // 判断审批人是否唯一
                asserts(res_3, chooseKey, templateNode);
                return res_3.get(0).getSysOperatorId();
            case 4:// 4=直属上级区域公司，通过岗位查询对应审批人
                OrgInfo my = orgInfoService.selectByPrimaryKey(bindOrgId);
                OrgInfo myParent = orgInfoService.selectByPrimaryKey(my.getParentId());
                // 必须当前公司是项目公司 且 父级公司是 区域公司
                if (my.getTypes().equals("3") && myParent.getTypes().equals("2")) {
                    StaffOfficeDomain where_4 = new StaffOfficeDomain();
                    where_4.setOrgId(myParent.getId());// 直属区域公司ID
                    where_4.setPostName(chooseKey); // 对应的岗位
                    List<StaffOfficeDomain> res_4 = staffOfficeService.selectStaffByPostName(where_4);
                    // 判断审批人是否唯一
                    asserts(res_4, chooseKey, templateNode);
                    return res_4.get(0).getSysOperatorId();
                }
                else {
                    throw new FlowProcessException("审批节点获取直属上级区域公司无效。请联系：流程管理员~");
                }
            case 5:// 5=总部公司，通过岗位查询对应审批人
                StaffOfficeDomain where_5 = new StaffOfficeDomain();
                where_5.setOrgId(BizParaUtil.get("super_org_id"));// 总部公司ID
                where_5.setPostName(chooseKey); // 对应的岗位
                List<StaffOfficeDomain> res_5 = staffOfficeService.selectStaffByPostName(where_5);
                // 判断审批人是否唯一
                asserts(res_5, chooseKey, templateNode);
                return res_5.get(0).getSysOperatorId();
            default:
                throw new FlowProcessException("节点选择标识配置错误。请联系：流程管理员~");*/
        //}
    }

    @Override
    public String checkUserId(String templateNodeId) {
        Object bindOrgIdObj = SessionUserUtils.getSessionAttribute("bindOrgId");
        Object bindDeptIdObj = SessionUserUtils.getSessionAttribute("bindDeptId");
        if (bindOrgIdObj == null || bindDeptIdObj == null) {
            throw new FlowProcessException("当前用户未绑定公司或部门，不能审批~");
        }
        // 审批节点
        TemplateNode templateNode = templateNodeService.selectByPrimaryKey(templateNodeId);
        if (templateNode == null) {
            throw new FlowProcessException("获取不到相应审批节点，有可能因：审批流程已调整~");
        }
        //节点选择标识 1=固定人员 2=本部门内 3=本公司内 4=上级区域公司 5=总部公司
        Integer routerFlag = templateNode.getRouteFlag();
        // 标识为1时，为审批人ID ，对应sys_operator ； 标识2-5时，对应岗位名称，比如2对应：部门负责人
        String chooseKey = templateNode.getChooseKey();
        // 当前用户所在的公司
        String bindOrgId = String.valueOf(bindOrgIdObj);
        // 当前用户所在的部门
        String bindDeptId = String.valueOf(bindDeptIdObj);

        // 根据选择标识，判断获取对应的审批人sys_operator_id
        switch (routerFlag) {
            case 1: // 直接返回审批人sys_operator_id
                return chooseKey;
            case 2: // 在本部门内找[部门负责人]岗位的人，获取其sys_operator_id
                StaffOfficeDomain where_2 = new StaffOfficeDomain();
                where_2.setOrgId(bindOrgId);
                where_2.setDeptId(bindDeptId);// 审批人所在的部门
                where_2.setPostName(chooseKey); // 对应的岗位，比如是 部门负责人
                List<StaffOfficeDomain> res_2 = staffOfficeService.selectStaffByPostName(where_2);
                // 判断审批人是否唯一
                asserts(res_2, chooseKey, templateNode);
                return res_2.get(0).getSysOperatorId();
            case 3:// 3=本公司(项目/区域)内，通过岗位查询对应审批人
                StaffOfficeDomain where_3 = new StaffOfficeDomain();
                where_3.setOrgId(bindOrgId);
                where_3.setPostName(chooseKey); // 对应的岗位
                List<StaffOfficeDomain> res_3 = staffOfficeService.selectStaffByPostName(where_3);
                // 判断审批人是否唯一
                asserts(res_3, chooseKey, templateNode);
                return res_3.get(0).getSysOperatorId();
            case 4:// 4=直属上级区域公司，通过岗位查询对应审批人
                OrgInfo my = orgInfoService.selectByPrimaryKey(bindOrgId);
                OrgInfo myParent = orgInfoService.selectByPrimaryKey(my.getParentId());
                // 必须当前公司是项目公司 且 父级公司是 区域公司
                if (my.getTypes().equals("3") && myParent.getTypes().equals("2")) {
                    StaffOfficeDomain where_4 = new StaffOfficeDomain();
                    where_4.setOrgId(myParent.getId());// 直属区域公司ID
                    where_4.setPostName(chooseKey); // 对应的岗位
                    List<StaffOfficeDomain> res_4 = staffOfficeService.selectStaffByPostName(where_4);
                    // 判断审批人是否唯一
                    asserts(res_4, chooseKey, templateNode);
                    return res_4.get(0).getSysOperatorId();
                }
                else {
                    throw new FlowProcessException("审批节点获取直属上级区域公司无效。请联系：流程管理员~");
                }
            case 5:// 5=总部公司，通过岗位查询对应审批人
                StaffOfficeDomain where_5 = new StaffOfficeDomain();
                where_5.setOrgId(BizParaUtil.get("super_org_id"));// 总部公司ID
                where_5.setPostName(chooseKey); // 对应的岗位
                List<StaffOfficeDomain> res_5 = staffOfficeService.selectStaffByPostName(where_5);
                // 判断审批人是否唯一
                asserts(res_5, chooseKey, templateNode);
                return res_5.get(0).getSysOperatorId();
            default:
                throw new FlowProcessException("节点选择标识配置错误。请联系：流程管理员~");
        }
    }

    /** 生成附件 **/
    private ProcessNodeAtt createFileAtt(AuthorizationVO vo, String processId, String nodeId,
                                         String file) {
        // 资料信息数组
        String[] fileAttStr = file.split("\\|");
        ProcessNodeAtt fileAtt = new ProcessNodeAtt();
        fileAtt.setId(fileAttStr[1]);
        fileAtt.setProcessId(processId);// 流程id
        fileAtt.setNodeId(nodeId);// 节点id
        String fileName = FilenameUtils.getBaseName(fileAttStr[0]);
        String suffix = FilenameUtils.getExtension(fileAttStr[0]).toLowerCase();// 后缀转小写
        fileAtt.setFileName(fileName);// 文件名
        fileAtt.setFileSuffix("." + suffix);// 文件后缀
        fileAtt.setFilePath(fileAttStr[2]);// 文件保存路径
        fileAtt.setAddBy(vo.getUserName());// 添加人
        fileAtt.setAddTime(new Date());// 添加时间
        return fileAtt;
    }

    /**
     * 判断审批人是否唯一
     * @param res
     * @param chooseKey
     * @param templateNode
     * @see
     */
    private void asserts(List<StaffOfficeDomain> res, String chooseKey, TemplateNode templateNode) {
        if (res == null || res.size() < 1) {
            throw new FlowProcessException("审批流程中绑定的岗位【" + chooseKey + "】，找不到关联的审批人。请联系：流程管理员~");
        }
        if (res.size() > 1) {
            StringBuilder sr = new StringBuilder("");
            for (StaffOfficeDomain var : res) {
                sr.append(var.getStaffName()).append(" ");
            }
            throw new FlowProcessException("审批流程中绑定的岗位【" + chooseKey + "】，关联到多个审批人：" + sr
                                           + "。请联系：流程管理员~");
        }
    }

    /**
     * 查询对应的处理人真实姓名
     */
    private Operator dealNameOf(String checkUserId) {
        Operator opt = operatorService.selectByPrimaryKey(checkUserId);
        if (opt == null) {
            return new Operator();
        }
        else {
            return opt;
        }
    }

    private StaffInfo getStaffInfoById(String staffId) {
        StaffInfo staffInfo = staffInfoService.selectByPrimaryKey(staffId);
        if (staffInfo == null) {
            return new StaffInfo();
        }
        else {
            return staffInfo;
        }

    }

    @Override
    public String proxyVisibleProCodes() {
        return wsStaffOfficeService.myAllVisibleProCodes();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void logicDel(String processId) {
        Process proc = processService.selectByPrimaryKey(processId);
        if (proc == null) {
            throw new FlowProcessException("获取不到对应的审批主数据~~");
        }
        // 获得关联业务表主键id
        String srcBizSguid = proc.getSrcBizSguid();
        // 获得关联业务表名
        String srcBizTable = proc.getSrcBizTable();
        AuthorizationVO vo = SessionUserUtils.getSessionAttributeForUserDtl();
        // 操作人ID
        String userId = vo.getId();
        // 直接修改原业务表数据的sql
        StringBuilder sql = new StringBuilder();
        sql.append("update ").append(srcBizTable).append(" set process_status='-9',upt_by=?,upt_time=sysdate where sguid='").append(
            srcBizSguid).append("'");
        // 原业务表审批状态 修改为审批状态
        String tempSql = sql.toString().replace("?", "'"+userId+"'");
        processService.updateBizTableProcStatus(tempSql);
    }
}
